﻿#pragma once

#include "DataObject.h"
#include "Logging.h"
#include "Object.h"
#include "Timer.h"



class Application;
class Mesh;
class System : public Object
{
public:
  System(const Configuration& cfg);
  virtual ~System(){};

  virtual void Init();
  virtual void InitVariable() {}
  virtual void Evolve() = 0;

  template<typename T>
  void AddCellVariable(const std::string& name)
  {
    _data_set.AddCellField(name, ArrayHandle<T>{});
  }

  template<typename T>
  void AddPointVariable(const std::string& name)
  {
    _data_set.AddPointField(name, ArrayHandle<T>{});
  }

  template<typename T>
  ArrayHandle<T> GetVariableArray(const std::string& name)
  {
    try
    {
      return _data_set.GetField(name).GetData().AsArrayHandle<ArrayHandle<T>>();
    }
    catch (const std::exception& e)
    {
      console::Error(e.what());
    }
  }

  const auto& GetDateSet() const { return this->_data_set; }

  auto& GetMesh() { return this->_mesh; }
  auto& App() { return this->_app; }
  auto& GetTimer() { return this->_timer; }

  /// <summary>
  /// BC type to Bounary name, 由AddBoundaryCondition函数填充
  /// [bc1]
  ///    type = Wall
  ///    boundary = 'upper bottom'
  /// [./]
  /// [bc2]
  ///     type = FarField
  ///     boundary = far_field
  /// [./]
  /// 
  /// 解析配置文件，填充 _bnd_name_2_bc_type
  /// </summary>
  void AddBoundaryCondition(const std::pair<std::string, std::vector<std::string>>& bc_pair);

  const std::map<std::string, BCType>& BoundaryNameToBCType() const ;

protected:
  DataSet _data_set;
  Application& _app;

  std::map<std::string, BCType> _bnd_name_2_bc_type;   

  /// <summary>
  /// 由子类定义，如：
  ///   _bc_name_2_bc_type["FarField"] = static_cast<BCType>(BCEnum::FarField);
  ///   _bc_name_2_bc_type["Wall"] = static_cast<BCType>(BCEnum::Wall);
  /// </summary>
  std::map<std::string, BCType> _bc_name_2_bc_type;  



  Mesh& _mesh;
  Timer _timer;
};
